﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using Microsoft.DirectX;

using NGE;

namespace MH.SE
{
    public partial class Main : Form
    {
        Game game;
        SECOM secom;
        string openedFile;
        Point move1stPos;
        Point move2ndPos;
        Point st_pos;

        int secomIndex;

        public Main()
        {
            InitializeComponent();
        }

        SceneComponent sceneCOM
        {
            get
            {
                return ((SceneComponent)game.GetComponent("SceneCOM"));
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            game = new Game("MH.SE", pictureBox1);
            secom = new SECOM(game);
            game.Unmount();
            secomIndex = game.Mount(secom);
            game.Start();

            sceneCOM.SCN = new Scene();

            sceneCOM.SCN.TileSize = tilePicker1.TileSize;
            for (int i = 0; i < 8; i++)
            {
                sceneCOM.SCN.Terrain.Layers.Add(new Terrain.Layer());
            }

            tilePicker1.GetFileList(game.Option.DataRootPath);
            tilePicker1.OnFileSelected += new TilePicker.OnSelected(tilePicker1_OnFileSelected);
            tilePicker1.OnRectSelected += new TilePicker.OnSelected(tilePicker1_OnRectSelected);

            sceneInfo1.LoadScene(game);
            sceneInfo1.refresh();
            entryInfo1.LoadScene(game);
            entryInfo1.refresh();
            npcInfo1.LoadScene(game);
            npcInfo1.refresh2();
            monsterEditer1.LoadScene(game);
            monsterEditer1.refresh();

            toolBox1.Init(game);
        }

        void tilePicker1_OnRectSelected()
        {
            secom.CursorDrawRect = tilePicker1.SelectRect;
            sceneCOM.SCN.TileSize = tilePicker1.TileSize;
        }

        void tilePicker1_OnFileSelected()
        {
            secom.CursorImg = tilePicker1.SelectFile;
        }


        private void 新建NToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        Vector3 getLocation(Point p)
        {
            //Vector3 v3 = new Vector3();
            int x = p.X;
            int y = p.Y;

            //x -= (int)offset.X*2;
            //y -= (int)offset.Y*2;
            //int xx = x;
            //int yy = y;
            //xx -= (int)secom.CursorLocation.X;
            //yy -= (int)secom.CursorLocation.Y;

            //xx /= (int)((double)sceneCOM.SCN.TileSize.Width * game.Option.Zoom);
            //yy /= (int)((double)sceneCOM.SCN.TileSize.Height * game.Option.Zoom); 
            
            x /= (int)((double)sceneCOM.SCN.TileSize.Width * game.Option.Zoom);
            y /= (int)((double)sceneCOM.SCN.TileSize.Height * game.Option.Zoom);

            st_pos = new Point(x, y);

            //x *= (int)((double)sceneCOM.SCN.TileSize.Width * game.Option.Zoom);
            //y *= (int)((double)sceneCOM.SCN.TileSize.Height * game.Option.Zoom);
            x *= sceneCOM.SCN.TileSize.Width;
            y *= sceneCOM.SCN.TileSize.Height;

            return Util.Point2Vector3(new Point(x, y));
        }

        void ctrlz()
        { 
        }
        void ctrly()
        { 
        }

        void drawTile(Vector3 v3)
        {
            if (tilePicker1.SelectFile == null)
            {
                return;
            }
            //tile.Frames[0].TextureIndexer.Name = tilePicker1.SelectFile.FullName;
            //tile.Frames[0].DrawZone = tilePicker1.SelectRect;
            for (int y = 0; y < tilePicker1.SelectRect.Height; y += sceneCOM.SCN.TileSize.Height)
            {
                for (int x = 0; x < tilePicker1.SelectRect.Width; x += sceneCOM.SCN.TileSize.Width)
                {
                    Terrain.Layer.Tile tile;

                    Vector3 v4 = v3;
                    v4.X += x;
                    v4.Y += y;
                    int i=sceneCOM.SCN.Terrain.Layers[sceneInfo1.SelectedLayer].GetTileIndex(v4);
                    if (i == -1)
                    {
                        tile = new Terrain.Layer.Tile();
                    }
                    else
                    {
                        tile = sceneCOM.SCN.Terrain.Layers[sceneInfo1.SelectedLayer].Tiles[i];
                    }
                    Image img = Image.FromFile(tilePicker1.SelectFile.FullPathAndFileName);

                    Rectangle rect = new Rectangle();
                    rect.X = tilePicker1.SelectRect.X + x;
                    rect.Y = tilePicker1.SelectRect.Y + y;
                    rect.Width = sceneCOM.SCN.TileSize.Width;
                    rect.Height = sceneCOM.SCN.TileSize.Height;

                    tile.Location = v3;
                    tile.Location.X += x;
                    tile.Location.Y += y;

                    int frm_index = toolBox1.SelectFRM;
                    for (int j = tile.Frames.Count; j <= frm_index; j++)
                    {
                        tile.Frames.Add(new Terrain.Layer.Tile.Frame());
                    }

                    tile.Frames[frm_index].TextureIndexer.Index=sceneCOM.SCN.AddTileImage(img, rect);
                    //Terrain.Layer.Tile.Frame frm = new Terrain.Layer.Tile.Frame();
                    //frm.TextureIndexer.Index = 
                    //tile.Frames.Add(frm);

                    if (i == -1)
                    {
                        sceneCOM.SCN.Terrain.Layers[sceneInfo1.SelectedLayer].AddTile(tile);
                    }
                }
            }
        }
        void drawZone(Rectangle rect)
        {
            for (int y = rect.Y; y < rect.Y + rect.Height; y += secom.CursorDrawRect.Height)
            {
                for (int x = rect.X; x < rect.X + rect.Width; x += secom.CursorDrawRect.Width)
                {
                    drawTile(new Vector3(x, y, 0));
                }
            }
        }
        void delTile(Vector3 v3)
        {
            for (int y = 0; y < tilePicker1.SelectRect.Height; y += sceneCOM.SCN.TileSize.Height)
            {
                for (int x = 0; x < tilePicker1.SelectRect.Width; x += sceneCOM.SCN.TileSize.Width)
                {
                    Vector3 v33 = v3;
                    v33.X += x;
                    v33.Y += y;
                    sceneCOM.SCN.Terrain.Layers[sceneInfo1.SelectedLayer].DelTile(v33);
                }
            }
        }
        void delZone(Rectangle rect)
        {
            for (int y = rect.Y; y < rect.Y + rect.Height; y += secom.CursorDrawRect.Height)
            {
                for (int x = rect.X; x < rect.X + rect.Width; x += secom.CursorDrawRect.Width)
                {
                    delTile(new Vector3(x, y, 0));
                }
            }
        }
        void drawCode(Vector3 v3,bool value)
        {
            if (sceneCOM.SCN.TileCodeLayer[v3] == null)
            {
                TileCode tc = new TileCode();
                tc.Location = v3;
                sceneCOM.SCN.TileCodeLayer[v3] = tc;
            }
            if (secom.DrawCodeIndex == 0)
            {
                sceneCOM.SCN.TileCodeLayer[v3].CHR = value;
            }
            else if (secom.DrawCodeIndex == 1)
            {
                sceneCOM.SCN.TileCodeLayer[v3].MTL = value;
            }
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                move1stPos = e.Location;
            }
            else if (e.Button == MouseButtons.Left)
            {
                secom.CursorLocation = Util.Vector3SubVector3(getLocation(e.Location), secom.SceneOffset);
                if (toolBox1.SelectPEN == 0)
                {
                    if (secom.CursorSelectedRect.Width < sceneCOM.SCN.TileSize.Width)
                    {
                        delTile(secom.CursorLocation);
                    }
                    else
                    {
                        delZone(secom.CursorSelectedRect);
                    }
                }
                else if (toolBox1.SelectPEN == 1)
                {
                    if (sceneInfo1.EditingCode)
                    {
                        drawCode(secom.CursorLocation,toolBox1.CANRCH);
                    }
                    else
                    {
                        drawTile(secom.CursorLocation);
                    }
                }
                else if (toolBox1.SelectPEN == 2) 
                {
                    drawZone(secom.CursorSelectedRect);
                }
                else if (toolBox1.SelectPEN == 3)
                {
                    secom.CursorSelectedRect.Size = new Size();
                    secom.CursorSelectedRect.Location = Util.Vector32Point(secom.CursorLocation);
                }
                else if (toolBox1.SelectPEN == 4) 
                {
                    //if (secom.CursorSelectedRect.Size.Equals(sceneCOM.SCN.TileSize))
                    {
                        Vector3 v3 = secom.CursorLocation;
                        int i = sceneCOM.SCN.Terrain.Layers[sceneInfo1.SelectedLayer].GetTileIndex(v3);
                        if (i > -1)
                        {
                            if (sceneCOM.SCN.TileCodeLayer == null)
                            {
                                sceneCOM.SCN.TileCodeLayer = new TileCodeLayer();
                            }
                            if (sceneCOM.SCN.TileCodeLayer[v3] == null)
                            {
                                TileCode tc = new TileCode();
                                tc.Location = v3;
                                sceneCOM.SCN.TileCodeLayer[v3] = tc;
                            }
                            CodeEditor ce = new CodeEditor();
                            ce.CODE = sceneCOM.SCN.TileCodeLayer[v3].Scrpit;
                            if (ce.ShowDialog() == DialogResult.OK)
                            {
                                sceneCOM.SCN.TileCodeLayer[v3].Scrpit = ce.CODE;
                            }
                        }
                    }
                }
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            secom.CursorLocation = Util.Vector3SubVector3( getLocation(e.Location),secom.SceneOffset);
            
            if (e.Button == MouseButtons.Right)
            {
                
            }
            else if (e.Button == MouseButtons.Left)
            {
                if (toolBox1.SelectPEN == 0)
                {
                    delTile(secom.CursorLocation);
                }
                if (toolBox1.SelectPEN == 1)
                {
                    if (sceneInfo1.EditingCode)
                    {
                        drawCode(secom.CursorLocation, toolBox1.CANRCH);
                    }
                    else
                    {
                        drawTile(secom.CursorLocation);
                    }
                }
            }
            else
            {

            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                move2ndPos = e.Location;

                Point offset = Util.PointSubPoint(move2ndPos, move1stPos);
                offset.X /= (int)((double)sceneCOM.SCN.TileSize.Width * game.Option.Zoom);
                offset.Y /= (int)((double)sceneCOM.SCN.TileSize.Height * game.Option.Zoom);
                offset.X *= sceneCOM.SCN.TileSize.Width;
                offset.Y *= sceneCOM.SCN.TileSize.Height;
                //offset.X *= (int)((double)sceneCOM.SCN.TileSize.Width * game.Option.Zoom);
                //offset.Y *= (int)((double)sceneCOM.SCN.TileSize.Height * game.Option.Zoom);
                //offset = Util.PointDivInt(offset, 2);
                secom.SceneOffset = Util.Vector3AddVector3(secom.SceneOffset, Util.Point2Vector3(offset));
            }
            else if (e.Button == MouseButtons.Left)
            {
                if (toolBox1.SelectPEN == 3)
                {
                    secom.CursorLocation = Util.Vector3SubVector3(getLocation(e.Location), secom.SceneOffset);
                    Point p = Util.PointSubPoint(Util.Vector32Point(secom.CursorLocation), secom.CursorSelectedRect.Location);
                    p.X += (int)(sceneCOM.SCN.TileSize.Width * 1);
                    p.Y += (int)(sceneCOM.SCN.TileSize.Height * 1);
                    secom.CursorSelectedRect.Size = new Size(p);
                    entryInfo1.Zone = secom.CursorSelectedRect;
                    monsterEditer1.Zone = secom.CursorSelectedRect;
                    //Graphics g = pictureBox1.CreateGraphics();
                    //g.DrawRectangle(Pens.Red, secom.CursorSelectedRect);
                    //pictureBox1.Refresh();
                }
            }
        }

        private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openedFile == null)
            {
                saveas();
            }
            else
            {
                save();
            }
        }

        private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            fd.RestoreDirectory = true;
            fd.Filter = "NGE Scene|*.nscn|XML|*.xml";
            if (fd.ShowDialog() == DialogResult.OK)
            {
                if (fd.FilterIndex == 1)
                {
                    secom.EnterScene(sceneCOM.LoadScene(fd.FileName));
                    //sceneCOM.SCN = (Scene)Util.LoadObject();

                    openedFile = fd.FileName;
                }
                else if (fd.FilterIndex == 2)
                {
                    secom.EnterScene(sceneCOM.LoadScene(fd.FileName));

                    openedFile = fd.FileName;
                }

                sceneInfo1.refresh();
                entryInfo1.refresh2();
                npcInfo1.refresh2();
                monsterEditer1.refresh();
                Text = "MH.SE - " + openedFile;
                secom.SceneOffset = new Vector3();
            }
        }
        bool tileUsed(Scene scn, int i)
        {
            if (scn.ExtendTile != null)
            {
                foreach (Terrain.Layer.Tile.Frame f in scn.ExtendTile.Frames)
                {
                    if (f.TextureIndexer.Index == i)
                    {
                        return true;
                    }
                }
            } 
            foreach (Terrain.Layer l in scn.Terrain.Layers)
            {
                foreach (Terrain.Layer.Tile t in l.Tiles)
                {
                    foreach (Terrain.Layer.Tile.Frame f in t.Frames)
                    {
                        if (f.TextureIndexer.Index == i)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        void optimze(Scene scn)
        {
            //List<NImage> bak = new List<NImage>();
            for (int i = 0; i < scn.TileImageSet.Count; i++)
            {
                if (tileUsed(scn, i))
                {
                    //bak.Add(scn.TileImageSet[i]);
                }
                else
                {
                    if(scn.TileImageSet[i]!=null)

                    scn.TileImageSet[i].Dispose();
                }
            }
            //scn.TileImageSet = null;
            //scn.TileImageSet = new List<NImage>();
            //scn.TileImageSet = bak;
            //return bak.Count;
        }
        void save()
        {
            optimze(sceneCOM.SCN);
            string str = new FileIndexer(openedFile).ExtName.ToLower();
            if (str == ".nscn")
            {
                Util.SaveObject(openedFile, sceneCOM.SCN);
                Util.SaveObjectXML(openedFile + ".xml", sceneCOM.SCN);
            }
            else if (str == ".xml")
            {
                Util.SaveObjectXML(openedFile, sceneCOM.SCN);
            }
            MessageBox.Show("保存成功");
        }
        void saveas()
        {
            optimze(sceneCOM.SCN);
            SaveFileDialog fd = new SaveFileDialog();
            fd.RestoreDirectory = true;
            fd.Filter = "NGE Scene|*.nscn|XML|*.xml";
            if (fd.ShowDialog() == DialogResult.OK)
            {
                if (fd.FilterIndex == 1)
                {
                    Util.SaveObject(fd.FileName, sceneCOM.SCN);
                    string str = new FileIndexer(openedFile).ExtName.ToLower();
                    if (str != ".xml")
                    {
                        Util.SaveObjectXML(openedFile + ".xml", sceneCOM.SCN);
                    }

                    openedFile = fd.FileName;
                    Text = Text + " - " + openedFile;
                }
                else if (fd.FilterIndex == 2)
                {
                    Util.SaveObjectXML(fd.FileName, sceneCOM.SCN);

                    openedFile = fd.FileName;
                    Text = Text + " - " + openedFile;
                }
                MessageBox.Show("保存成功");
            }
        }
        private void 另存为AToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveas();
        }

        private void 撤消UToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ctrlz();
        }

        private void 重复RToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ctrly();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            secom.DrawCode = sceneInfo1.EditingCode;
            secom.DrawCodeIndex = sceneInfo1.CodeLayer;
            Point p = st_pos;

            int x = (int)secom.SceneOffset.X;
            int y = (int)secom.SceneOffset.Y;

            x /= (int)((double)sceneCOM.SCN.TileSize.Width);
            y /= (int)((double)sceneCOM.SCN.TileSize.Height);

            p = Util.PointSubPoint(p, new Point(x, y));

            toolStripStatusLabel1.Text = "鼠标坐标=" + p + " FPS=" + game.FPS + " 图块数量=" + sceneCOM.SCN.TileImageSet.Count;

        }

        private void mP3转NSoundToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
            info.FileName = "NGE.ToNSound.exe";
            //info.Arguments = "text.txt";
            //info.WorkingDirectory = "c://";
            System.Diagnostics.Process pro;
            try
            {
                pro = System.Diagnostics.Process.Start(info);
            }
            catch
            { }
        }

        private void pNGToolStripMenuItem_Click(object sender, EventArgs e)
        {System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo();
            info.FileName = "NGE.ToNImage.exe";
            //info.Arguments = "text.txt";
            //info.WorkingDirectory = "c://";
            System.Diagnostics.Process pro;
            try
            {
                pro = System.Diagnostics.Process.Start(info);
            }
            catch
            { }
            
        }

        private void monsterEditer1_Load(object sender, EventArgs e)
        {

        }
    }
}
